package com.lanyam.travel.base.service.impl;


import com.fasterxml.jackson.core.type.TypeReference;
import com.lanyam.travel.base.dao.DistrRecordMapper;
import com.lanyam.travel.base.dao.DistrUserMapper;
import com.lanyam.travel.base.dao.TravelOrderMapper;
import com.lanyam.travel.base.entity.*;
import com.lanyam.travel.base.entity.vo.CaseWithdraVo;
import com.lanyam.travel.base.dao.CaseWithdraMapper;
import com.lanyam.travel.base.entity.vo.DistrRecordVo;
import com.lanyam.travel.base.entity.vo.DistrSettingResult;
import com.lanyam.travel.base.entity.vo.DistrUserVo;
import com.lanyam.travel.base.service.ICaseWithdraService;
import com.lanyam.travel.base.service.ICashSettingService;
import com.lanyam.travel.base.service.IDistrRecordService;
import com.lanyam.travel.base.service.IDistrSettingService;
import com.lanyam.travel.base.utils.JSONResult;
import com.lanyam.travel.base.utils.JsonMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.*;
import javax.annotation.Resource;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.metadata.IPage;


@Service
@Transactional
@Slf4j
public class CaseWithdraServiceImpl implements ICaseWithdraService {

    @Resource
    private CaseWithdraMapper caseWithdraMapper;
    @Resource
    private DistrUserMapper distrUserMapper;
    @Resource
    private TravelOrderMapper travelOrderMapper;
    @Autowired
    private ICashSettingService cashSettingService;
    @Autowired
    private IDistrSettingService distrSettingService;
    @Autowired
    private DistrRecordMapper distrRecordMapper;

    @Override
    public IPage<CaseWithdraVo> getPageCaseWithdra (Map<String, Object> queryMap, Integer page, Integer rows) {
        Page<CaseWithdraVo> pageSize = new Page<CaseWithdraVo>(page, rows);
        Page<CaseWithdraVo> pageInfo = caseWithdraMapper.getPage(pageSize, queryMap);
        return pageInfo;
    }

    @Override
    public void addCaseWithdra(CaseWithdra caseWithdra) {
        caseWithdraMapper.insert(caseWithdra);
    }

    @Override
    public void updateCaseWithdra(CaseWithdra caseWithdra) {
        CaseWithdraVo byId = caseWithdraMapper.getById(caseWithdra.getId());
        Integer oldHasWithdra = byId.getHasWithdra();
        Integer newHasWithdra = caseWithdra.getHasWithdra();
        // 将提现金额添加到分销用户余额
        if (oldHasWithdra != newHasWithdra) {
            DistrUser distrUser = new DistrUser();
            if (newHasWithdra==1) {
                distrUser.setUserId(caseWithdra.getCwdUserid());
                distrUser.setAmount(caseWithdra.getCashAmout());
                distrUserMapper.addAmountByUserId(distrUser);
                caseWithdra.setCreateTime(new Date());
            } else if (newHasWithdra == 0) {
                distrUser.setUserId(caseWithdra.getCwdUserid());
                distrUser.setAmount(caseWithdra.getCashAmout().multiply(new BigDecimal(-1)));
                distrUserMapper.addAmountByUserId(distrUser);
                caseWithdra.setCreateTime(null);
            }
        }
        caseWithdraMapper.updateById(caseWithdra);
    }

    @Override
    public void delById(String id) {
        caseWithdraMapper.delById(id);
    }

    @Override
    public void calcCash() {
        Date date = new Date();
        CashSetting settingData = cashSettingService.getSettingData();
        // 获取未计算分销提现的订单列表
        List<TravelOrder> notCalcOrderList = travelOrderMapper.getNotCalcOrderList(date);
        for (TravelOrder travelOrder : notCalcOrderList) {
            // 查询订单是否存在分销商，不存在分销商则无需计算
            String userId = travelOrder.getOrderUserid();
            String disUserId = travelOrder.getDistrUserId();
            String oId = travelOrder.getId();
            BigDecimal payAmount = travelOrder.getRealAmount();
            // 判断是线下购买还是线上购买
            if (disUserId == null) {   // 线上购买
                DistrUserVo distrUserByUserId = distrUserMapper.getDistrUserByUserId(userId);
                if (distrUserByUserId != null && distrUserByUserId.getId() != null) {
                    String distrUserId = distrUserByUserId.getId();
                    List<DistrRecordVo> distrRecords = distrRecordMapper.getListByOrderId(travelOrder.getId());
                    // 保存分销提成历史
//                    saveRecordList(distrRecords);
                    // 记录提现数据
                    for (DistrRecord distrRecord : distrRecords) {
                        calcWithdra(distrRecord, settingData);
                    }
                }
            } else {
//                DistrUserVo distrUserByUserId = distrUserMapper.getDistrUserByUserId(disUserId);
                String distrUserId = disUserId;
                List<DistrRecordVo> distrRecords = distrRecordMapper.getListByOrderId(travelOrder.getId());
                // 保存分销提成历史
//                saveRecordList(distrRecords);
                // 记录提现数据
                for (DistrRecord distrRecord : distrRecords) {
                    calcWithdra(distrRecord, settingData);
                }
            }
        }
        // 更新订单提现状态
        travelOrderMapper.updateCalcCashStatus(date);
    }

    /**
     * 计算提现信息
     * @param distrRecord
     * @param cashSetting
     */
    private void calcWithdra(DistrRecord distrRecord, CashSetting cashSetting) {
        Integer isAuto = cashSetting.getIsAuto();   // 0-手动，1-自动
        BigDecimal lowerServCharge = cashSetting.getLowerServCharge();
        BigDecimal servCharge = cashSetting.getServCharge();
        // 提现入账记录保存
        CaseWithdra caseWithdra = new CaseWithdra();
        caseWithdra.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        BigDecimal amount = distrRecord.getAmount();
        caseWithdra.setCwdUserid(distrRecord.getUserId());
        caseWithdra.setCashAmout(amount);
        caseWithdra.setServCharge(servCharge);
        caseWithdra.setSetAuto(isAuto);
        caseWithdra.setHasWithdra(isAuto);
        caseWithdraMapper.insert(caseWithdra);
        // 如果是自动提现，则把提现余额保存到分销用户账号下
        if (isAuto == 1) {
            DistrUser distrUser = new DistrUser();
            distrUser.setUserId(distrUser.getUserId());
            distrUser.setAmount(caseWithdra.getCashAmout());
            distrUserMapper.addAmountByUserId(distrUser);
        }
    }

    /**
     * 保存distrRecordList
     * @param list
     */
    private void saveRecordList(List<DistrRecord> list) {
        for (DistrRecord distrRecord: list) {
            distrRecordMapper.insert(distrRecord);
        }
    }

    /**
     * 计算分销提现信息（从当前等级计算）
     * @return
     */
    public List<DistrRecordVo> calcDistrRecord(String orderId) {
        // 获取当前订单的分销用户id
        TravelOrder travelOrder = travelOrderMapper.selectById(orderId);
        BigDecimal orderPrice = travelOrder.getRealAmount();
        String distrUserId = travelOrder.getDistrUserId();
        if (distrUserId==null) {
            String userid = travelOrder.getOrderUserid();
            DistrUserVo distrUser = distrUserMapper.getDistrUserByUserId(userid);
            if (distrUser != null)
                distrUserId = distrUser.getId();
        }
        if (distrUserId == null)
            return null;
        // 如果当前订单存在分销用户，再进行计算分销
        String userId = distrUserMapper.getUserIdByDistrUserId(distrUserId);
        List<DistrUser> list = new ArrayList<>();
        String fatherUserid = distrUserId;
        while (fatherUserid != null) {
            DistrUser distrUser = distrUserMapper.selectById(fatherUserid);
            if (distrUser == null)
                break;
            list.add(distrUser);
            fatherUserid = distrUser.getFatherUserid();
        }
        DistrUser distrUserLevel0 = null;
        DistrUser distrUserLevel1 = null;
        DistrUser distrUserLevel2 = null;
        DistrUser distrUserLevel3 = null;
        for (DistrUser distrUser : list) {
            Integer dislevel = distrUser.getDislevel();
            if (dislevel == 1) {
                distrUserLevel1 = distrUser;
            } else if (dislevel == 2) {
                distrUserLevel2 = distrUser;
            } else if (dislevel == 3) {
                distrUserLevel3 = distrUser;
            } else if (dislevel == 0) {
                distrUserLevel0 = distrUser;
            }
        }
        Map<String, DistrSettingResult> distrSettingMap = getDistrSettingMap();
        DistrSettingResult levelZero = distrSettingMap.get("levelZero");
        DistrSettingResult levelOne = distrSettingMap.get("levelOne");
        DistrSettingResult levelTwo = distrSettingMap.get("levelTwo");
        DistrSettingResult levelThree = distrSettingMap.get("levelThree");
        List<DistrRecordVo> resultList = new ArrayList<>();
        // 计算业务员提成
        if (levelZero != null && distrUserLevel0 != null && distrUserLevel0.getAuditStatus()==9) {
            DistrRecordVo distrRecord = new DistrRecordVo();
            Integer disType = levelZero.getDisType();
            BigDecimal cost = BigDecimal.ZERO;
            if (disType == 0) {
                cost = orderPrice.multiply(levelZero.getDisNum());
            } else {
                cost = levelZero.getDisNum();
            }
            distrRecord.setId(UUID.randomUUID().toString().replaceAll("-",""));
            distrRecord.setAmount(cost);
            distrRecord.setOrderId(orderId);
            distrRecord.setUserId(userId);
            distrRecord.setDistUserId(distrUserLevel0.getId());
            distrRecord.setCreateTime(new Date());
            distrRecord.setDislevel(0);
            distrRecord.setUserName(distrUserLevel0.getUserName());
            resultList.add(distrRecord);
        }
        // 计算分销1
        if (distrUserLevel1 != null && levelOne != null && distrUserLevel1.getAuditStatus()==9) {
            DistrRecordVo distrRecord = new DistrRecordVo();
            Integer disType = levelOne.getDisType();
            BigDecimal cost = BigDecimal.ZERO;
            if (disType==0) { // 百分比
                cost = orderPrice.multiply(levelOne.getDisNum());
            } else {
                cost = levelOne.getDisNum();
            }
            distrRecord.setId(UUID.randomUUID().toString().replaceAll("-",""));
            distrRecord.setAmount(cost);
            distrRecord.setOrderId(orderId);
            distrRecord.setUserId(userId);
            distrRecord.setDistUserId(distrUserLevel1.getId());
            distrRecord.setCreateTime(new Date());
            distrRecord.setDislevel(1);
            distrRecord.setUserName(distrUserLevel1.getUserName());
            resultList.add(distrRecord);
        }
        // 计算分销2
        if (distrUserLevel2 != null && levelTwo != null && distrUserLevel2.getAuditStatus()==9) {
            DistrRecordVo distrRecord = new DistrRecordVo();
            Integer disType = levelOne.getDisType();
            BigDecimal cost = BigDecimal.ZERO;
            if (disType==0) { // 百分比
                cost = orderPrice.multiply(levelTwo.getDisNum());
            } else {
                cost = levelTwo.getDisNum();
            }
            distrRecord.setId(UUID.randomUUID().toString().replaceAll("-",""));
            distrRecord.setAmount(cost);
            distrRecord.setOrderId(orderId);
            distrRecord.setUserId(userId);
            distrRecord.setDistUserId(distrUserLevel2.getId());
            distrRecord.setCreateTime(new Date());
            distrRecord.setDislevel(2);
            distrRecord.setUserName(distrUserLevel2.getUserName());
            resultList.add(distrRecord);
        }
        // 计算分销3
        if (distrUserLevel3 != null && levelThree != null && distrUserLevel3.getAuditStatus()==9) {
            DistrRecordVo distrRecord = new DistrRecordVo();
            Integer disType = levelOne.getDisType();
            BigDecimal cost = BigDecimal.ZERO;
            if (disType==0) { // 百分比
                cost = orderPrice.multiply(levelThree.getDisNum());
            } else {
                cost = levelThree.getDisNum();
            }
            distrRecord.setId(UUID.randomUUID().toString().replaceAll("-",""));
            distrRecord.setAmount(cost);
            distrRecord.setOrderId(orderId);
            distrRecord.setUserId(userId);
            distrRecord.setDistUserId(distrUserLevel3.getId());
            distrRecord.setCreateTime(new Date());
            distrRecord.setDislevel(3);
            distrRecord.setUserName(distrUserLevel3.getUserName());
            resultList.add(distrRecord);
        }
        return resultList;
    }

    /**
     * 获取分销设置列表
     * @return
     */
    private List<DistrSettingResult> getDistrSettingList() {
        DistrSetting settingData = distrSettingService.getSettingData();
        String settingInfo = settingData.getSettingInfo();
        // 获取分销员提成信息
        List<DistrSettingResult> settingList = JsonMapper.string2Obj(settingInfo, new TypeReference<List<DistrSettingResult>>() {
        });
        // 获取并添加业务员提成信息
        if (settingData.getSaleType() != null && settingData.getSaleNum() != null) {
            DistrSettingResult distrSettingResult = new DistrSettingResult();
            distrSettingResult.setDislevel(0);
            distrSettingResult.setDisType(settingData.getSaleType());
            distrSettingResult.setDisNum(settingData.getSaleNum());
            settingList.add(distrSettingResult);
        }
        return settingList;
    }

    /**
     * 获取分销设置map
     * @return
     */
    private Map<String , DistrSettingResult> getDistrSettingMap() {
        Map<String, DistrSettingResult> map = new HashMap<>();
        List<DistrSettingResult> distrSettingList = getDistrSettingList();
        for (DistrSettingResult distrSettingResult : distrSettingList) {
            Integer dislevel = distrSettingResult.getDislevel();
            if (dislevel == 1) {
                map.put("levelOne", distrSettingResult);
            } else if (dislevel == 2) {
                map.put("levelTwo", distrSettingResult);
            } else if (dislevel == 3) {
                map.put("levelThree", distrSettingResult);
            } else if (dislevel == 0) {
                map.put("levelZero", distrSettingResult);
            }
        }
        return map;
    }
}